package crawlerv2;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;

public class Main {
	private static GnutellaGraph mGraph;
	private static Thread master;

	private static void PrintUsage() {
		System.out.println("Error: incorrect inputs");
		System.out.println("Usage: crawler <host:port> <time>");
		System.out
				.println("  <host:port> is the node to be used as a bootstrapping point");
		System.out
				.println("  <time> is the length of time after which to stop crawling");
		System.out
				.println("    *** note: time is in milliseconds and must be >= 0");
		System.out
				.println("              after this time, no new queries will be issued");
		System.out.println("\n");
	}

	public static void main(String[] args) {

		String nodeAddress = new String();
		int nodePort = 0;
		long timeout = 0;
		int mode = 0;
		int TCP_timeout = 0;

		String tokens[] = args[0].split(":");

		nodeAddress = tokens[0];
		nodePort = Integer.parseInt(tokens[1]);

		System.out.println("Starting Thread with " + nodeAddress + ":"
				+ nodePort);
		master = new MasterInput(nodeAddress, nodePort);
		master.start();

		Date start = new Date();
		mGraph = new GnutellaGraph(512, 512);
		CrawlerVector mainCrawler = new CrawlerVector();

		while (true) {

			if (((MasterInput) master).isCrawl())
				CrawlNodes(mainCrawler);
		}

	}

	private static void ProcessResult(CrawlResultVector result) {
		// result.PrintResult();
		mGraph.ProcessResult(result);
		mGraph.GenerateHTML("WWW");
		// mGraph.DrawToFile("TestImage");
	}

	private static void CrawlNodes(CrawlerVector mainCrawler) {
		CrawlResultVector newResult;
		int nodePort;
		String nodeAddress;
		if (((MasterInput) master).isNewBootStrap()) {
			nodeAddress = ((MasterInput) master).getCrawlHost();
			nodePort = ((MasterInput) master).getCrawlPort();
			((MasterInput) master).setFalseNewBootStrap();

		} else {
			String addressAndPort = mGraph.GetAddressToCrawl();
			if (addressAndPort == null) {
				System.out.println("Could not find node to crawl...");
				return;
			}
			String tokens[] = addressAndPort.split(":");
			nodeAddress = tokens[0];
			nodePort = Integer.parseInt(tokens[1]);

		}
		newResult = mainCrawler.crawlvector(nodeAddress, nodePort);
		if (newResult == null) {
			mGraph.NotifyCrawlFailure(nodeAddress + ":" + nodePort);
			return;
		}

		// newResult.PrintResult();
		ProcessResult(newResult);

	}

	private static void bootStrapNewNode() {

	}

}

class MasterInput extends Thread {

	private String Host;
	private int Port;
	private boolean crawl;
	private String crawlHost;
	private int crawlPort;
	private boolean newBootStrap;

	public MasterInput(String nodeAddress, int nodePort) {
		this.Host = nodeAddress;
		this.Port = nodePort;
		this.crawl = false;
		newBootStrap = false;
	}

	public void run() {
		Socket socket;
		BufferedReader reader;
		PrintWriter writer;
		String s = "";
		try {
			socket = new Socket(Host, Port);
			System.out.println("Connecting to node : " + Host + " on port "
					+ Port);
			// socket.setSoTimeout(TCP_timeout); //set timeout

			reader = new BufferedReader(new InputStreamReader(socket
					.getInputStream()));
			writer = new PrintWriter(socket.getOutputStream(), true);

			String line = "";
			do {
				line = reader.readLine();
				System.out.println(line);
				if (line.equals("crawlyes"))
					crawl = true;
				else
					crawl = false;
				if (line.startsWith("crawlnode ")) {
					newBootStrap = true;
					line = line.substring(10);
					crawlHost = line.split(":")[0];
					try {
						crawlPort = Integer.parseInt((line.split(":"))[1]);
					} catch (NumberFormatException e) {
						crawlPort = 0;
					}

				}

			} while (!line.trim().equals("Terminate"));

			System.exit(0);

		} catch (Exception err) {
			System.err.println(err);
		}

	}

	public boolean isCrawl() {
		return crawl;
	}

	public String getCrawlHost() {
		return Host;
	}

	public int getCrawlPort() {
		return Port;
	}

	public boolean isNewBootStrap() {
		return newBootStrap;
	}

	public void setFalseNewBootStrap() {
		newBootStrap = false;
	}
}
